package divtastic.js;

import js.Dom;
import js.Lib;


class DisplayDiv
{
    
    public var fixedTextWidth:  Int;
    public var fixedTextHeight: Int;
    
    // TODO: possibly remove
    public var _d:              Int;
    
    // TODO: Check if this should be public?
    public var _dom:            HtmlDom;
    
    private var _y:             Float;
    private var _x:             Float;
    private var _width:         Float;
    private var _height:        Float;
    private var _style:         Style;
    private var _bgColor:       String;
    private var _img:           String;
    private var _tile:          Bool;
    private var offSetX:        Int;
    private var offSetY:        Int;

    private var viz:            Bool;
    
    // NOTE: Divtastic properties here so we can take them into account in getGlobalXY etc...
    
    private var _scale:         Float;
    private var _scaleY:        Float;
    private var _scaleX:        Float;
    private var _alpha:         Float;
    private var _rotation:      Float;
    private var _angle:         Int;
    
    // NOTE: Not currently used possibly store affines when tested more.
    public var afflines:        Array<Float>;
    
    //TODO: Take into account rotation and scale?
    public function getGlobalXY():List<Float>
    {
        
        var p = this;
        var gX = p.x;
        var gY = p.y;
        
        while( p.parent != null )
        {
            
            p = p.parent;
            gX += p.x;
            gY += p.y;
            
        }
        var pos: List<Float> = new List();
        pos.add( gX );
        pos.add( gY );
        return pos;
        
    }
    
    
    // TODO: change this for DispatchTo Signals... 
    public function setPress( func: Void -> Dynamic )
    {
        
        var f = func;
        _dom.onmousedown = function( e: Event )
        {
            f();
        }
        
    }
    
    
    public function setRelease( func: Void -> Dynamic )
    {
        
        var f = func;
        _dom.onmouseup = function( e: Event )
        {
            f();
        }
        
    }
    
    public function setOver( func: Void -> Dynamic )
    {
        
        var f = func;
        _dom.onmouseover = function( e: Event )
        {
            f();
        }
        
    }
    
    
    public function setOut( func: Void -> Dynamic )
    {
        
        var f = func;
        _dom.onmouseout= function( e: Event )
        {
            f();
        }
        
    }
    
    
    /*
    
    TODO: Implement and check this.
    
    public function setupDrag()
    {
        
        var me = this;
        _here.onmousedown = function( e: Event )
        {
            
            me.offSetX = Std.int( e.clientX - me.parent.x );
            me.offSetY = Std.int( e.clientY - me.parent.y );
            
            //me.startDrag();
        }
        _here.onmouseup = function( e: Event )
        {
            //me.stopDrag();
        }
        
    }
        public function stopDrag()
    {
        _here.onmousemove = null;
    }
    
    public function startDrag( )
    {
        
        _here.onmousemove = drag;
        
    }
    private function drag( e: Event )
    {
        
        x = e.clientX - offSetX;
        y = e.clientY - offSetY;
        
    }
    
    */
    
    
    public function setupParentDrag()
    {
        
        var me              = this;
        _style.cursor       = "pointer";
        _dom.onmousedown   = function( e: Event )
        {
            //trace( e.clientX + ' ' + e.clientY + ' ' + e.screenX + ' ' + e.screenY );
            //trace('mousedown');
            me.offSetX = Std.int( e.clientX - me.parent.x );
            me.offSetY = Std.int( e.clientY - me.parent.y );
            me.parentStartDrag();
        }
        _dom.onmouseup = function( e: Event )
        {
            //trace('mouseup');
            me.parentStopDrag();
        }
        
    }
    
    
    public function parentStartDrag()
    {
        
        Lib.document.onmousemove = parentDrag;
        
    }
    
    
    public function parentStopDrag()
    {
        
        Lib.document.onmousemove = null;
        
    }
    
    
    private function parentDrag( e: Event )
    {
        
        parent.x = e.clientX - offSetX;
        parent.y = e.clientY - offSetY;
        
    }
    
    
    public function new( ?img: String )
    {
        
        _dom           = js.Lib.document.createElement( "div" );
        _style          = _dom.style; 
        setTile( false );
        if( img != null )
        {
            
            setImage( img );
            
        }
        
        
        _style.position = "absolute";
        //_style.overflow  = 'Hidden';
        _d = 0;
        
    }
    
    
    public function setImage( img: String )
    {
        
        _img = img;
        
        if( img.split('.').length > 1 )
        {
            //trace('setting image to ' + img );
            _style.backgroundImage = 'url(' + img +')';
            
        }
        else
        {
            
            _dom.className = img ;
            
        }
        
    }
    
    
    // for width and height to be adjustable ( tweenable ) you need to set this.
    public function setClip()
    {
        
        _style.overflow  = 'Hidden';
        
    }
    
    
    public var tile( getTile, setTile ):Bool;
    
    
    private function getTile():Bool
    {
        
        if( _tile == null )
        {
            
            setTile( false ) ;
            
        }
        return _tile ;
        
    }
    
    
    private function setTile( tile_: Bool ):Bool
    {
        
        _tile = tile_;
        if( _tile )
        {
            
            _style.backgroundRepeat = 'repeat';
            
        }
        else
        {
            
            _style.backgroundRepeat = 'no-repeat';
            
        }
        return tile_;
        
    }
    
    
    public function getInstance():                  HtmlDom
    {
        
        return _dom;
        
    }
    
    
    public function getStyle():                     Style
    {
        
        return _style;
        
    }
    
    
    public var text( get_text, set_text ):          String;
    
    public function set_text( txt: String ):        String
    {
        
        // TODO: look at this code not sure it is ideal but seems useful at moment.
        _dom.innerHTML = '';
        
        set_width( 0 );
        set_height( 0 );
        if( parent != null )
        {
            parent.updateSizeBasedOnChild( this );
        }
        
        _dom.innerHTML = txt;
        // TODO: not ideal to have browser type in this class think about moving?
        switch( Browser.browserType )
        {
            case Mozilla:   untyped _style.MozUserSelect = 'none';
            case WebKit:    untyped _style.webkitUserSelect = 'none';
            case IE, Opera: untyped _style.unselectable = 'on';
        }
        
        set_width( _width );
        set_height( _height );
        if( parent != null )
        {
            parent.updateSizeBasedOnChild( this );
        }
        
        return txt;
        
    }
    
    
    public function updateText( txt: String )
    {
        
        _dom.innerHTML = '';
        set_width( 0 );
        set_height( 0 );
        _dom.innerHTML = txt;
        _style.width = Std.string( fixedTextWidth );
        if( fixedTextHeight != null )
        {
            _style.height = Std.string( fixedTextHeight );
        }
        _style.overflow  = 'Hidden';
        
    }
    
    
    public function get_text():                     String
    {
        
        return _dom.innerHTML;
        
    }
    
    
    public var visible( get_visible, set_visible ): Bool;
    
    public function set_visible( val: Bool ):       Bool
    {
        
        //TODO: consider collapse
        
        if( val )
        {
            
            _style.visibility = "visible"; 
            
        } 
        else
        {
            
            _style.visibility = "hidden"; 
            
        }
        
        viz = val;
        
        return viz;
        
    }
    
    
    public function get_visible():                  Bool
    {
        
        if( viz == null )
        {
            
            viz = true;
            
        }
        
        return viz;
        
    }
    
    
    public var fill( get_fill, set_fill ):          String;
    
    public function set_fill( c: String ):          String
    {
        
        _bgColor = c;
        _style.backgroundColor = c;
        return c;
        
    }
    
    
    public function get_fill():                     String
    {
        
        return _bgColor;
        
    }
    
    
    public var height( get_height, set_height ):    Float;
    public function set_height( val: Float ):      Float
    {
        
        _height = val;
        _style.paddingTop = val + "px";
        return val;
        
    }
    public function get_height():                  Float
    {
        
        if( _height == null || _height < _dom.clientHeight )
        {
            _height = _dom.clientHeight;
        }
        return _height;
        
    }
    
    
    public var width( get_width, set_width ):       Float;
    public function set_width( val: Float ):       Float
    {
        
        _width = val;
        _style.paddingLeft = val + "px";
        return val;
        
    }
    private function get_width():                   Float
    {   
        
        if( _width == null || _width < _dom.clientWidth )
        {
            _width = _dom.clientWidth;
        }
        return _width;
        
    }
    
    
    public var y( get_y, set_y ):                   Float;
    private function set_y( val: Float ):           Float
    {
        
        _y = val;
        _style.top = val + "px";
        return val;
        
    }
    private function get_y():                       Float
    {
        
        return _y;
        
    }
    
    public var x( get_x, set_x ):                   Float;
    private function set_x( val: Float ):           Float
    {
        
        _x = val;
        _style.left = val + "px";
        return val;
        
    }
    private function get_x():                       Float
    {
        
        return _x;
        
    }
    
    public function addChild( mc: DisplayDiv ): DisplayDiv
    {
        
        _dom.appendChild( mc.getInstance() );
        mc.parent = this;
        updateSizeBasedOnChild( mc );
        mc.appended();
        return mc;
        //trace( 'new width ' +  mc.width );
    }
    
    public function appended()
    {
        
        
        
    } 
    
    public var _parent:                                     DisplayDiv;
    public var parent( get_parent, set_parent ):            DisplayDiv;
    
    public function set_parent( mc: DisplayDiv ):  DisplayDiv
    {
        
        _parent = mc;
        return mc;
        
    }
    
    
    public function get_parent():                           DisplayDiv
    {
        
        return _parent;
        
    }
    
    
    public function updateSizeBasedOnChild( mc: DisplayDiv )
    {
        
        if( width < mc.width + mc.x )
        {
            
            set_width( mc.width + mc.x );
            
        }
        
        if( height < mc.height + mc.y )
        {
            
            set_height( mc.height + mc.y );
            
        }
        
        
        
    }
    
    
}